<template>
    <a-modal v-model:visible="visible" centered wrap-class-name="region-dialog" :width="820"
        :after-close="handleAfterClose" :footer="footer" @ok="handleOk" @cancel="handleCancel">
        <template #title>
            <slot name="title"> 区域选择 </slot>
        </template>
        <scrollbar v-if="region.length" class="region-dialog__scrollbar">
            <div class="flex items-center">
                <a-checkbox :checked="checkedCity.length === allCityLen" @change="handleCheckAll">全选</a-checkbox>
                <a-select v-if="!lock" placeholder="在此处搜索推广区域" :value="checkedCity" class="region-selector"
                    mode="multiple" show-search :max-tag-count="8" @select="handleSelectorChange"
                    @deselect="handleDeSelectorChange">
                    <a-select-opt-group :key="province.id" v-for="province in region[0].children">
                        <template #label>{{ province.name_cn }}</template>
                        <a-select-option :value="city.name_cn" :province="province.name_cn" :key="city.id"
                            v-for="city in province.children" />
                    </a-select-opt-group>
                </a-select>
            </div>
            <div :key="province.id" v-for="province in region[0].children" class="flex mt-5">
                <a-checkbox class="flex-shrink-0 region-province"
                    :checked="innerCityMap[province.name_cn].length === province.children.length"
                    @change="handleProvinceChange(province, $event)">{{ province.name_cn }}</a-checkbox>
                <a-checkbox-group class="region-checkbox" :value="innerCityMap[province.name_cn]"
                    :options="mapCityName(province.children)" @change="handleCheckCity(province.name_cn, $event)" />
            </div>
            <div class="flex mt-5">
                <div class="flex-shrink-0 region-province">
                    <a-checkbox disabled></a-checkbox><span class="ml-2 cursor-pointer">敬请期待</span>
                </div>
                <a-checkbox-group :value="[]" class="region-checkbox">
                    <a-checkbox>香港</a-checkbox>
                    <a-checkbox>澳门</a-checkbox>
                    <a-checkbox>台湾</a-checkbox>
                </a-checkbox-group>
            </div>
        </scrollbar>
    </a-modal>
</template>

<script setup lang="ts">
import { computed, reactive, watch } from 'vue'
import { reactiveComputed, useVModel } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { useRegionStore, type Region } from '@/store/useRegionStore'
import Scrollbar from '@/components/scrollbar/index.vue'
import { cloneDeep } from 'lodash-es'
import is from '@/utils/is'

interface Props {
    show: boolean
    selected?: string
    footer?: string | null
    lock?: boolean
    max?: number
}

interface Emits {
    (e: 'change', v: Record<string, string[]>): void
    (e: 'limit', v: Record<string, string[]>): void
}

const props = withDefaults(defineProps<Props>(), {
    show: false,
    selected: '',
    footer: undefined,
    lock: false
})

const emit = defineEmits<Emits>()

const regionStore = useRegionStore()
const { region, mapChineseRegion, mapRegion } = storeToRefs(regionStore)
const visible = useVModel(props, 'show')

const defaultCityMap = () => {
    return (
        (region.value[0]?.children ?? []).reduce<Record<string, string[]>>((init, province) => {
            init[province.name_cn] = []
            return init
        }, {}) ?? {}
    )
}

const prevInnerCityMap = reactive(defaultCityMap())

const innerCityMap = reactiveComputed(() => {
    return defaultCityMap()
})

const allCityLen = computed(() => {
    return (region.value[0]?.children ?? []).reduce<number>((count, province) => {
        return count + province.children.length
    }, 0)
})

const checkedCity = computed(() => {
    return Object.keys(innerCityMap).reduce<string[]>(
        (checkedList, province) => checkedList.concat(innerCityMap[province]),
        []
    )
})

// 这个watch是用来监听回填的地区字段(selected)
watch(
    () => [props.selected, props.show],
    ([, show]) => {
        if (!show) return

        const makeAreas = props.selected.split(',')

        if (makeAreas.some((area) => ['全国', '中国'].includes(area))) {
            handleCheckAll(true, false)
        } else {
            makeAreas.forEach((area) => {
                const parent = mapChineseRegion.value[area]?.parent

                if (parent) {
                    const nameCn = mapRegion.value[parent]?.name_cn
                    if (nameCn && is.array(innerCityMap[nameCn])) {
                        innerCityMap[nameCn].push(area)
                    }
                }
            })
        }
    }
)

// 全国
const countryWide = computed(() => {
    return checkedCity.value.length === allCityLen.value
})

function handleCheckCity(province: string, city: string[], lock = props.lock) {
    if (lock) return
    innerCityMap[province] = city
}

function handleProvinceChange(province: Region, value: any, lock = props.lock) {
    if (lock) return
    const checked = value.target.checked

    innerCityMap[province.name_cn] = checked ? mapCityName(province.children) : []
}

function mapCityName(city: Region[]) {
    return city.map((c) => c.name_cn)
}

function handleSelectorChange(value: string, option: any) {
    if (props.lock) return
    innerCityMap[option.province].push(value)
}

function handleDeSelectorChange(value: string, option: any) {
    if (props.lock) return
    const cityList = innerCityMap[option.province]
    const i = cityList.indexOf(value)
    cityList.splice(i, 1)
}

function handleCheckAll(e: any | boolean, lock = props.lock) {
    if (lock) return
    const checked = is.boolean(e) ? e : e.target.checked

        ; (region.value[0]?.children ?? []).forEach((province) => {
            // checked=false就全部设置为空数组(置空)
            innerCityMap[province.name_cn] = checked ? mapCityName(province.children) : []
        })
}

function handleOk() {
    if (is.number(props.max)) {
        if (checkedCity.value.length > props.max) {
            emit('limit', innerCityMap)
            return
        }
    }

    emit('change', innerCityMap)
    visible.value = false
}

function handleCancel() {
    Object.assign(innerCityMap, prevInnerCityMap)
}

function handleAfterClose() {
    Object.assign(prevInnerCityMap, cloneDeep(innerCityMap))
}

function handleReset() {
    Object.assign(innerCityMap, defaultCityMap())
    Object.assign(prevInnerCityMap, defaultCityMap())
}

defineExpose({
    handleReset,
    countryWide
})
</script>

<style lang="scss" scoped>
.region {
    height: 80%;
}

.region-province {
    width: 90px;
    position: relative;
    border-right: 1px dashed grey;
}

.region-selector {
    width: 600px;
    margin-left: 70px;
}

.region-checkbox {
    padding-left: 30px;

    ::v-deep(.ant-checkbox) {
        display: none;
    }

    ::v-deep(.ant-checkbox + span) {
        padding: 2px 10px;
    }

    &::v-deep(.ant-checkbox.ant-checkbox-checked + span) {
        background: #ff4d4f;
        color: #fff;
        border-radius: 5px;
        padding: 2px 10px;
    }

    &::v-deep(.ant-checkbox-wrapper:nth-child(n + 12)) {
        margin-top: 8px;
    }
}
</style>

<style lang="scss">
.region-dialog {
    .ant-modal-content {
        height: 90vh;
        overflow: auto;
    }

    .ant-modal-body {
        height: calc(100% - 55px - 53px);
        padding-right: 0;
    }

    &__scrollbar {
        height: 100%;
        padding-right: 24px;
    }
}
</style>